/**
 * 
 */
package view;

import java.awt.event.ItemEvent;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.DefaultCellEditor;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import table.CheckboxEditor;
import table.CheckboxRenderer;
import table.ColumnData;
import table.ComboboxEditor;
import table.ComboboxRenderer;
import table.DesignTableModel;
import table.TableModel;
import tree.IconCellRenderer;
import tree.IconData;
import model.Model;
import combobox.ComboboxModel;
import combobox.ListboxItem;
import gui.CodeBehind;
import gui.Form;
import helper.DBHelper;
import helper.TableHelper;
import controller.Controller;
import database.Database;
import database.Field;
import database.Row;
import database.Table;

/**
 * @author Ken
 *
 */
public class View implements Observer{
	private Controller _controller;
	private Model _model;
	private Form f;
	/**
	 * @return the _controller
	 */
	public Controller get_controller() {
		return _controller;
	}

	/**
	 * @param _controller the _controller to set
	 */
	public void set_controller(Controller _controller) {
		this._controller = _controller;
	}
	
	public View() {
		_controller = new Controller();
	}
	
	public View(Controller c, Model m, Form f){
		_controller = c;
		_model = m;
		this.f = f;
	}
	
	public String renderGUI(Form form){		
		return "Fail";		
	}

	public void createDatabase(Form f, String data) {
		String result = _controller.createDatabase(data);
		if  (result.equals("Success"))
		{
			Database db = _model.getDatabase(data);
			((ComboboxModel)f.jComboBox1.getModel()).addDatabase(db.get_name());
			DefaultMutableTreeNode node = new DefaultMutableTreeNode(new IconData(IconCellRenderer.ICON_DATABASE, db.get_name()), true);
			javax.swing.tree.DefaultTreeModel tree_model = new DefaultTreeModel(node, true);
			DBHelper helper = new DBHelper(db.get_name(), tree_model);
			if (f._dbLinkTree.size() <= 0)
				f.jTree1.setModel(tree_model);
			f._dbLinkTree.add(helper);
		}
		else
			f.showMessageDialog(result, "Error", JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * @return the _model
	 */
	public Model get_model() {
		return _model;
	}

	/**
	 * @param _model the _model to set
	 */
	public void set_model(Model _model) {
		this._model = _model;
	}

	public void removeDatabase(Form f, String name) {
		String result = _controller.removeDatabase(name);
		if (result.equals("Success"))
		{
			((ComboboxModel)f.jComboBox1.getModel()).removeDatabase(name);
			f.jComboBox1.revalidate();
		}
		else
		{
			f.showMessageDialog(result, "Error", JOptionPane.ERROR_MESSAGE);
		}		
	}

	public void createTable(Form f, String dbName, String tbName) {
		String result = _controller.createTable(dbName, tbName);
		if (result.equals("Success")){		
			Database db = _model.getDatabase(dbName);
			Table t = db.getTable(tbName);
			DefaultMutableTreeNode node = new DefaultMutableTreeNode(new IconData(IconCellRenderer.ICON_TABLE, t.get_name()), false);
			DefaultTreeModel model = (DefaultTreeModel) f.jTree1.getModel();
			DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
		    root.add(node);             
		    model.reload(root);
		    ListboxItem item = (ListboxItem)f.jComboBox1.getSelectedItem();
		    item.set_selectedTable(tbName);
		    CodeBehind.initJTable();
		}
		else
		{	
			f.showMessageDialog(result, "Error", JOptionPane.ERROR_MESSAGE);
		}
	}

	/*
	 * Trieu goi khi user thay doi database trong combobox
	 */
	public void databaseChange(Form f, ItemEvent evt) {
		String db = CodeBehind.getSelectedDatabase(f.jComboBox1);		
		for (int i = 0; i < f._dbLinkTree.size(); i++) {
			DBHelper h = f._dbLinkTree.get(i);
			if (h._database == db){
				f.jTree1.setModel(h._treeModel);
				return;
			}
		}
	}

	public void saveDatabase(Form f, String name){		
		String result = _model.saveDatabase(name);
		f.showMessageDialog(result, "Informaltion", JOptionPane.INFORMATION_MESSAGE);
	}
	
	public void saveTable(Form f, String dbName, String tName) {
		JTable property = null, data = null;
		int index = 0;
		while (index < f._tableHelper.size()){
			TableHelper helper = f._tableHelper.get(index);
			if (helper.databaseName.equals(dbName)){
				if (helper.tableName.equals(tName))
				{
					property = helper.modelProperty;
					data = helper.modelData;
					break;
				}
			}
			index++;
		}
		if (property != null){
			TableModel model = (TableModel) property.getModel();
			int rowIndex = 0;
			List<List<String>> TableData = new ArrayList<List<String>>();
			while (rowIndex < model.getRowCount()){
				List<String> row = model.getRow(rowIndex);
				TableData.add(row);
				index++;
			}
			Table t = _model.getTable(dbName, tName);
			if (t != null)
			{
				if (t.get_fields().size() <= 0){
					_model.saveDatabase(dbName, tName, TableData, null);
				}				
			}
		}
	}

	public void loadModel(Form f) {		
		List<Database> db = _model.get_databases();		
		((ComboboxModel)f.jComboBox1.getModel()).removeAllElements();
		f._tableHelper.clear();
		f._dbLinkTree.clear();
		
		for (int i = 0; i < db.size(); i++) {
			Database database = db.get(i);			
			((ComboboxModel)f.jComboBox1.getModel()).addDatabase(database.get_name());
			DefaultMutableTreeNode node = new DefaultMutableTreeNode(new IconData(IconCellRenderer.ICON_DATABASE, database.get_name()), true);
			javax.swing.tree.DefaultTreeModel tree_model = new DefaultTreeModel(node, true);
			
			for (int j = 0; j < database.get_tables().size(); j++) {
				Table t = database.getTable(j);
				DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(new IconData(IconCellRenderer.ICON_TABLE, t.get_name()), false);				
			    node.add(childNode);             			    			    
			    JTable property = getPropertyTable(t);			    
			    JTable data = getDataTable(t, property);
			    TableHelper helper = new TableHelper(t.get_name(),database.get_name(), property, data); 
			    f._tableHelper.add(helper);
			    ((TableModel)property.getModel()).set_helper(helper);
			    ((TableModel)data.getModel()).set_helper(helper);
			}
			tree_model.reload(node);
			DBHelper helper = new DBHelper(database.get_name(), tree_model);						
			f._dbLinkTree.add(helper);
		}
		
		ListboxItem item = (ListboxItem)f.jComboBox1.getSelectedItem();
		if (item == null)
			return;
		String dbName = item.getData();
		javax.swing.tree.DefaultTreeModel model = null;
		int index = 0;		
		while (index < f._dbLinkTree.size())
		{
			DBHelper h = f._dbLinkTree.get(index); 
			if (h._database.equals(dbName))
			{
				model = h._treeModel;
				break;
			}
			index++;
		}
		f.jTree1.setModel(model);	
				
//		if (f.jTabbedPane1.getComponentCount() > 0) {
//			for (int i = 0; i < f.jTabbedPane1.getTabCount(); i++) {
//				String title = f.jTabbedPane1.getTitleAt(i);
//				JScrollPane scroll = (JScrollPane) f.jTabbedPane1.getComponent(i);
//				JTable table = (JTable) scroll.getViewport().getView();
//				String tbName = title.substring(0, title.indexOf('-')).trim();
//				String tbType = title.substring(title.indexOf('-') + 1).trim();
//				int ind = 0;
//				while (ind < f._tableHelper.size()) {
//					TableHelper helper = f._tableHelper.get(ind);
//					if (helper.tableName.toLowerCase().equals(tbName.toLowerCase())) {
//						if (tbType.toLowerCase().equals("data")) {
//							table.setModel(helper.modelData.getModel());
//							table.revalidate();
//							break;
//						}
//						if (tbType.toLowerCase().equals("design")) {
//							table.setModel(helper.modelProperty.getModel());
//							table.revalidate();
//							break;
//						}
//					}
//					ind++;
//				}
//			}
//		}		
		f.jTabbedPane1.removeAll();
	}

	private JTable getDataTable(Table t, JTable prop) {
		List<Row> data = t.get_rows();
		TableModel modelProperty = (TableModel)prop.getModel();
		int numCol = modelProperty.getRowCount();
		TableModel model = new TableModel();
		for (int i = 0; i < numCol; i++) {
			model.getM_columns().add(new ColumnData(modelProperty.getValueAt(i, 1).toString(), 200, JLabel.CENTER));
		}
		JTable table;
		if (data != null && data.size() > 0) {			
			for (int i = 0; i < data.size(); i++) {
				Row r = data.get(i);
				List<String> row = new ArrayList<String>();
				for (int j = 0; j < r.get_data().size(); j++) {
					row.add(r.get_data().get(j).toString());
				}
				model.addRow(row);
			}			
		}
		table = new JTable(model);		
		return table;
	}

	private JTable getPropertyTable(Table t) {
		TableModel model = new DesignTableModel();
		JTable table;
		List<Field> fields = t.get_fields();
		if (fields != null && fields.size() > 0)
		{
			for (int i = 0; i < fields.size(); i++) {
				Field f = fields.get(i);
				List<String> row = new ArrayList<String>();
				String b = new Boolean(f.is_isPrimary()).toString();
				row.add(b);
				row.add(f.get_name());
				row.add(f.get_dataType());
				model.addRow(row);
			}					
		}		
		table = new JTable(model);
		table.setRowHeight(20);
		table.setCellEditor(new DefaultCellEditor(new JTextField()));
		TableColumnModel tcm = table.getColumnModel();                        	
		TableColumn tc = tcm.getColumn(0);
		tc.setCellRenderer(new CheckboxRenderer());       
		tc.setCellEditor(new CheckboxEditor());
		tc = tcm.getColumn(2);
		tc.setCellRenderer(new ComboboxRenderer());
		tc.setCellEditor(new ComboboxEditor());
		return table;
	}
	
	public void saveTable(Form f, String db, String tName, List<List<String>>props, List<List<String>>rows){
		boolean flag = checkTrigger(props, rows);
		if (!flag)
		{
			f.showMessageDialog("Data Error, Please Check Trigger", "Error", JOptionPane.ERROR_MESSAGE);
			return;
		}		
		String result = _model.saveDatabase(db, tName, props, rows);		
		initTable(f, db, tName);
	}

	private boolean checkTrigger(List<List<String>> props,
			List<List<String>> rows) {
		List<Field> fields = new ArrayList<Field>();
		int[]primaryKey = new int[props.size()];
		int idx = 0;
		for (int i = 0; i < props.size(); i++) {
			List<String> r = props.get(i);
			Field f = new Field(r.get(1), r.get(2));
			Boolean b = new Boolean(r.get(0));
			f.set_isPrimary(b);
			if (b == true)			
				primaryKey[idx++] = i;
			fields.add(f);
		}
		Hashtable<String, Boolean>[] dics = new Hashtable[idx];
		for (int i = 0; i < idx; i++) {
			dics[i] = new Hashtable<String, Boolean>();
		}
		boolean isError = true;
		for (int i = 0; i < rows.size(); i++) {
			List<String> row = rows.get(i);
			isError = isError & (fields.size() == row.size());
			for (int j = 0; j < idx; j++) {
				isError = isError & (row.get(j) != null && !row.get(j).equals(""));
				if (dics[j].containsKey(row.get(j)))
					return false;
				dics[j].put(row.get(j), true);								
			}
			if (!isError)
				return false;
		}		
		return true;
	}

	public void saveTableProperty(Form f, String db, String tName,
			List<List<String>> rows) {
		String result = _model.saveDatabase(db, tName, rows, null);
		initTable(f, db, tName);
		_model.saveDatabase(db, tName, null, rows);	
//		if (result.equals("Success")) {
//			int index = 0;
//			while (index < f._tableHelper.size()) {
//				TableHelper helper = f._tableHelper.get(index);
//				if (helper.databaseName.equals(db) && helper.tableName.equals(tName)) {
//					
//				}
//				index++;
//			}
//		}
		//TODO: cho nay co the nang cap them ve sau
	}

	private void initTable(Form f, String db, String tName) {
		int index = 0;
		while (index < f._tableHelper.size()) {
			TableHelper helper = f._tableHelper.get(index);
			if (helper.databaseName.equals(db) && helper.tableName.equals(tName)) {				
				helper.propertyEdited = false;
				table.TableModel modelData = new TableModel();
				modelData.setM_columns(new ArrayList<ColumnData>());
				TableModel propModel = (TableModel)helper.modelProperty.getModel();
				for (int i = 0; i < propModel.getRowCount(); i++) {
					modelData.getM_columns().add(new ColumnData(propModel.getValueAt(i, 1).toString(), 200, JLabel.CENTER));						
				}
				
				helper.dataEdited = false;																
				Table t = _model.getTable(db, tName);				
				List<Row> rows = t.get_rows();
				for (int i = 0; i < rows.size(); i++) {
					Row r = rows.get(i);
					List<Object> objs = r.get_data();
					List<String> s = new ArrayList<String>();
					for (int j = 0; j < objs.size(); j++) {
						s.add(objs.get(j).toString());
					}
					modelData.addRow(s);					
				}				
				helper.modelData.setModel(modelData);
				helper.modelData.revalidate();
				((TableModel)helper.modelData.getModel()).set_helper(helper);				
			}					
			index++;
		}																		    				
	}

	public void saveTableData(Form f, String db, String tName, List<List<String>> rows) {
		_model.saveDatabase(db, tName, null, rows);		
	}

	@Override
	public void update(Observable o, Object arg) {
		loadModel(f);
	}

	public void deleteTable(Form f, String database, String tableName) {
		_model.deleteDatabase(database, tableName);
		loadModel(f);
	}
}
